package com.gitee.wsl.text.template

/*
import com.gitee.wsl.text.CharPredicate
import com.gitee.wsl.text.Substring
import com.gitee.wsl.text.Substring.RepeatingPattern
import com.gitee.wsl.text.Substring.SubPattern
import com.gitee.wsl.text.Substring.SubPatternMatch
import com.gitee.wsl.text.Substring.before
import com.gitee.wsl.text.Substring.consecutive
import com.gitee.wsl.text.Substring.first
import com.gitee.wsl.text.Substring.suffix
import com.gitee.wsl.text.whileNotNull
import java.util.AbstractList
import java.util.Collections
import java.util.Optional
import java.util.function.BiConsumer
import java.util.function.BiFunction
import java.util.function.BinaryOperator
import java.util.function.Function
import java.util.function.Supplier
import java.util.stream.Collector
import java.util.stream.Collectors
import java.util.stream.Collectors.toList
import java.util.stream.Stream


*/
/**
 * The API of StringFormat. Allows different subclasses to use different placeholder styles.
 *//*

abstract class AbstractStringFormat(
    private val format: String, placeholdersPattern: RepeatingPattern, wildcard: String
) {
   
    // The string literals between placeholders
    val fragments: List<String>
    private val toCapture: List<Boolean>
    private val numCapturingPlaceholders: Int
    init {
        val delimiters = Stream.builder<String>()
        val toCapture = Stream.builder<Boolean>()
        placeholdersPattern.split(format).forEachOrdered { literal: SubPatternMatch ->
            delimiters.add(literal.toString())
            toCapture.add(!literal.isFollowedBy((wildcard)))
        }
        fragments = delimiters.build().collect(toList())
        this.toCapture = chop(toCapture.build().collect(toList()))
        numCapturingPlaceholders = fragments.size - 1 - (this.toCapture.stream().filter { c: Boolean? -> !c!! }
            .count().toInt())
    }

    */
/**
     * Parses `input` and applies the `mapper` function with the single placeholder value
     * in this string format.
     *
     *
     * For example:
     *
     * <pre>`new StringFormat("Job failed (job id: {job_id})").parse(input, jobId -> ...);
    `</pre> *
     *
     * @return the return value of the `mapper` function if not null. Returns empty if `input` doesn't match the format, or `mapper` returns null.
     * @throws IllegalArgumentException if or the format string doesn't have exactly one placeholder.
     *//*

    fun <R> parse(input: String, mapper: Function<in String, out R>): Optional<R> {
        return parseExpecting(1, input, onlyElement(mapper))
    }

    */
/**
     * Parses `input` and applies `mapper` with the two placeholder values in this string
     * format.
     *
     *
     * For example:
     *
     * <pre>`new StringFormat("Job failed (job id: '{id}', error code: {code})")
     * .parse(input, (jobId, errorCode) -> ...);
    `</pre> *
     *
     * @return the return value of the `mapper` function if not null. Returns empty if `input` doesn't match the format, or `mapper` returns null.
     * @throws IllegalArgumentException if or the format string doesn't have exactly two placeholders.
     *//*

    fun <R> parse(
        input: String, mapper: BiFunction<in String, in String, out R>
    ): Optional<R> {
        return parseExpecting(2, input, combining(mapper))
    }

    */
/**
     * Similar to [.parse], but parses `input` and applies `mapper` with the *3* placeholder values in this string format.
     *
     *
     * For example:
     *
     * <pre>`new StringFormat("Job failed (job id: '{job_id}', error code: {code}, error details: {details})")
     * .parse(input, (jobId, errorCode, errorDetails) -> ...);
    `</pre> *
     *
     * @return the return value of the `mapper` function if not null. Returns empty if `input` doesn't match the format, or `mapper` returns null.
     * @throws IllegalArgumentException if or the format string doesn't have exactly 3 placeholders.
     *//*

    */
/*fun <R> parse(input: String, mapper: Ternary<in String, out R>): Optional<R> {
        return parseExpecting(3, input, combining(mapper))
    }*//*


    */
/**
     * Similar to [.parse], but parses `input` and applies `mapper` with the *4* placeholder values in this string format.
     *
     * @return the return value of the `mapper` function if not null. Returns empty if `input` doesn't match the format, or `mapper` returns null.
     * @throws IllegalArgumentException if or the format string doesn't have exactly 4 placeholders.
     *//*

    */
/*fun <R> parse(
        input: String, mapper: Quarternary<in String, out R>
    ): Optional<R> {
        return parseExpecting(4, input, combining(mapper))
    }*//*


    */
/**
     * Similar to [.parse], but parses `input` and applies `mapper` with the *5* placeholder values in this string format.
     *
     * @return the return value of the `mapper` function if not null. Returns empty if `input` doesn't match the format, or `mapper` returns null.
     * @throws IllegalArgumentException if or the format string doesn't have exactly 5 placeholders.
     *//*

    */
/*fun <R> parse(input: String, mapper: Quinary<in String, out R>): Optional<R> {
        return parseExpecting(5, input, combining(mapper))
    }*//*


    */
/**
     * Similar to [.parse], but parses `input` and applies `mapper` with the *6* placeholder values in this string format.
     *
     * @return the return value of the `mapper` function if not null. Returns empty if `input` doesn't match the format, or `mapper` returns null.
     * @throws IllegalArgumentException if or the format string doesn't have exactly 6 placeholders.
     *//*

    */
/*fun <R> parse(input: String, mapper: Senary<in String, out R>): Optional<R> {
        return parseExpecting(6, input, combining(mapper))
    }*//*


    */
/**
     * Parses `input` against the pattern.
     *
     *
     * Returns an immutable list of placeholder values in the same order as [.placeholders],
     * upon success; otherwise returns empty.
     *
     *
     * The [Substring.SubPatternMatch] result type allows caller to inspect the characters around each
     * match, or to access the raw index in the input string.
     *//*

    fun parse(input: String): Optional<List<SubPatternMatch>> {
        return internalParse(input, fragments, toCapture)
    }

    private fun internalParse(
        input: String, fragments: List<String>, toCapture: List<Boolean>
    ): Optional<List<SubPatternMatch>> {
        checkUnformattability()
        if (!input.startsWith(fragments.get(0))) { // first literal is the prefix
            return Optional.empty<List<Substring.SubPatternMatch>>()
        }
        val builder: MutableList<Substring.SubPatternMatch> =
            ArrayList<Substring.SubPatternMatch>(numCapturingPlaceholders)
        var inputIndex = fragments.get(0).length
        val numPlaceholders = numPlaceholders()
        for (i in 1..numPlaceholders) {
            // subsequent delimiters are searched left-to-right; last literal is the suffix.
            val trailingLiteral: Substring.SubPattern = if (i < numPlaceholders) first(fragments.get(i)) else suffix(fragments.get(i))
            val placeholder: SubPatternMatch = before(trailingLiteral).`in`(input, inputIndex).orElse(null) ?: return Optional.empty<List<Substring.SubPatternMatch>>()
            if (toCapture[i - 1]) {
                builder.add(placeholder)
            }
            inputIndex = placeholder.index() + placeholder.length + fragments.get(i).length
        }
        return optional(inputIndex == input.length, Collections.unmodifiableList(builder))
    }

    */
/**
     * Returns an Optional that wraps `value` if `condition` is true and `value` is
     * not null, or else `empty()`.
     *
     *
     * Example: `Optional<Foo> foo = optional(input.hasFoo(), input.getFoo());`
     *
     * @since 3.7
     *//*

    open fun <T : Any> optional(condition: Boolean, value: T): Optional<T> {
        return if (condition) Optional.ofNullable(value) else Optional.empty()
    }

    */
/**
     * Parses `input` and applies `mapper` with the single placeholder value in this
     * format string.
     *
     *
     * For example:
     *
     * <pre>`new StringFormat("Job failed (job id: {job_id})").parseOrThrow(input, jobId -> ...);
    `</pre> *
     *
     *
     * Unlike [.parse], `IllegalArgumentException` is thrown if the
     * input string doesn't match the string format. The error message will include both the input
     * string and the format string for ease of debugging, but is otherwise generic. If you need a
     * different exception type, or need to customize the error message, consider using [ ][] instead and call [Optional.orElseThrow] explicitly.
     *
     * @return the return value of the `mapper` function if not null. Returns empty if `input` doesn't match the format, or `mapper` returns null.
     * @throws IllegalArgumentException if the input string doesn't match the string format, or if the
     * format string doesn't have exactly one placeholder
     * @throws NullPointerException if any of the parameter is null or `mapper` returns null.
     * @since 7.0
     *//*

    fun <R> parseOrThrow(input: String, mapper: Function<in String, R>): R {
        return parseOrThrowExpecting(1, input, onlyElement(mapper))
    }

    */
/**
     * Parses `input` and applies `mapper` with the two placeholder values in this format
     * string.
     *
     *
     * For example:
     *
     * <pre>`new StringFormat("Job failed (job id: '{job_id}', error code: {error_code})")
     * .parseOrThrow(input, (jobId, errorCode) -> ...);
    `</pre> *
     *
     *
     * Unlike [.parse], `IllegalArgumentException` is thrown if the
     * input string doesn't match the string format. The error message will include both the input
     * string and the format string for ease of debugging, but is otherwise generic. If you need a
     * different exception type, or need to customize the error message, consider using [ ][] instead and call [Optional.orElseThrow] explicitly.
     *
     * @return the return value of the `mapper` function applied on the extracted placeholder
     * value.
     * @throws IllegalArgumentException if the input string doesn't match the string format, or if the
     * format string doesn't have exactly two placeholders
     * @throws NullPointerException if any of the parameter is null or `mapper` returns null.
     * @since 7.0
     *//*

    fun <R> parseOrThrow(
        input: String, mapper: BiFunction<in String, in String, R>
    ): R {
        return parseOrThrowExpecting(2, input, combining(mapper))
    }

    */
/**
     * Similar to [.parseOrThrow], but parses `input` and applies
     * `mapper` with the *3* placeholder values in this format string.
     *
     *
     * For example:
     *
     * <pre>`new StringFormat("Job failed (id: '{job_id}', code: {error_code}, error details: {details})")
     * .parseOrThrow(input, (jobId, errorCode, errorDetails) -> ...);
    `</pre> *
     *
     *
     * Unlike [.parse], `IllegalArgumentException` is thrown if the
     * input string doesn't match the string format. The error message will include both the input
     * string and the format string for ease of debugging, but is otherwise generic. If you need a
     * different exception type, or need to customize the error message, consider using [ ][] instead and call [Optional.orElseThrow] explicitly.
     *
     * @return the return value of the `mapper` function applied on the extracted placeholder
     * values.
     * @throws IllegalArgumentException if the input string doesn't match the string format, or if the
     * format string doesn't have exactly 3 placeholders
     * @throws NullPointerException if any of the parameter is null or `mapper` returns null.
     * @since 7.0
     *//*

    */
/*fun <R> parseOrThrow(input: String, mapper: Ternary<in String, R>): R {
        return parseOrThrowExpecting(3, input, combining(mapper))
    }*//*


    */
/**
     * Similar to [.parseOrThrow], but parses `input` and applies
     * `mapper` with the *4* placeholder values in this string format.
     *
     *
     * Unlike [.parse], `IllegalArgumentException` is thrown if
     * the input string doesn't match the string format. The error message will include both the input
     * string and the format string for ease of debugging, but is otherwise generic. If you need a
     * different exception type, or need to customize the error message, consider using [ ][] instead and call [Optional.orElseThrow] explicitly.
     *
     * @return the return value of the `mapper` function applied on the extracted placeholder
     * values.
     * @throws IllegalArgumentException if the input string doesn't match the string format, or if the
     * format string doesn't have exactly 4 placeholders
     * @throws NullPointerException if any of the parameter is null or `mapper` returns null.
     * @since 7.0
     *//*

    */
/*fun <R> parseOrThrow(input: String, mapper: Quarternary<in String, R>): R {
        return parseOrThrowExpecting(4, input, combining(mapper))
    }*//*


    */
/**
     * Similar to [.parseOrThrow], but parses `input` and applies
     * `mapper` with the *5* placeholder values in this string format.
     *
     *
     * Unlike [.parse], `IllegalArgumentException` is thrown if the
     * input string doesn't match the string format. The error message will include both the input
     * string and the format string for ease of debugging, but is otherwise generic. If you need a
     * different exception type, or need to customize the error message, consider using [ ][] instead and call [Optional.orElseThrow] explicitly.
     *
     * @return the return value of the `mapper` function applied on the extracted placeholder
     * values.
     * @throws IllegalArgumentException if the input string doesn't match the string format, or if the
     * format string doesn't have exactly 5 placeholders
     * @throws NullPointerException if any of the parameter is null or `mapper` returns null.
     * @since 7.0
     *//*

    */
/*fun <R> parseOrThrow(input: String, mapper: Quinary<in String, R>): R {
        return parseOrThrowExpecting(5, input, combining(mapper))
    }*//*


    */
/**
     * Similar to [.parseOrThrow], but parses `input` and applies
     * `mapper` with the *6* placeholder values in this string format.
     *
     *
     * Unlike [.parse], `IllegalArgumentException` is thrown if the
     * input string doesn't match the string format. The error message will include both the input
     * string and the format string for ease of debugging, but is otherwise generic. If you need a
     * different exception type, or need to customize the error message, consider using [ ][] instead and call [Optional.orElseThrow] explicitly.
     *
     * @return the return value of the `mapper` function applied on the extracted placeholder
     * values.
     * @throws IllegalArgumentException if the input string doesn't match the string format, or if the
     * format string doesn't have exactly 6 placeholders
     * @throws NullPointerException if any of the parameter is null or `mapper` returns null.
     * @since 7.0
     *//*

    */
/*fun <R> parseOrThrow(input: String, mapper: Senary<in String, R>): R {
        return parseOrThrowExpecting(6, input, combining(mapper))
    }*//*


    */
/**
     * Similar to [.parse], parses `input` and applies `mapper`
     * with the single placeholder value in this format string, but matches the placeholders backwards
     * from the end to the beginning of the input string.
     *
     *
     * For unambiguous strings, it's equivalent to [.parse], but if for
     * example you are parsing "a/b/c" against the pattern of "{parent}/{...}", `parse("a/b/c",
     * parent -> parent)` results in "a", while `parseGreedy("a/b/c", parent -> parent)` results
     * in "a/b".
     *
     *
     * This is also equivalent to allowing the left placeholder to match greedily, while still
     * requiring the remaining placeholder(s) to be matched.
     *
     * @return the return value of the `mapper` function if not null. Returns empty if `input` doesn't match the format, or `mapper` returns null.
     * @throws IllegalArgumentException if the format string doesn't have exactly one placeholder.
     * @since 7.0
     *//*

    fun <R> parseGreedy(
        input: String, mapper: Function<in String, out R>
    ): Optional<R> {
        return parseGreedyExpecting(1, input, onlyElement(mapper))
    }

    */
/**
     * Similar to [.parse], parses `input` and applies `mapper`
     * with the two placeholder values in this format string, but matches the placeholders backwards
     * from the end to the beginning of the input string.
     *
     *
     * For unambiguous strings, it's equivalent to [.parse], but if for
     * example you are parsing "a/b/c" against the pattern of "{parent}/{child}", `parse("a/b/c", (parent, child) -> ...)` parses out "a" as parent and "b/c" as child, while
     * `parseGreedy("a/b/c", (parent, child) -> ...)` parses "a/b" as parent and "c" as child.
     *
     *
     * This is also equivalent to allowing the left placeholder to match greedily, while still
     * requiring the remaining placeholder(s) to be matched.
     *
     * @return the return value of the `mapper` function if not null. Returns empty if `input` doesn't match the format, or `mapper` returns null.
     * @throws IllegalArgumentException if the format string doesn't have exactly two placeholders.
     * @since 7.0
     *//*

    fun <R> parseGreedy(
        input: String, mapper: BiFunction<in String, in String, out R>
    ): Optional<R> {
        return parseGreedyExpecting(2, input, combining(mapper))
    }

    */
/**
     * Similar to [.parse], parses `input` and applies `mapper`
     * with the 3 placeholder values in this format string, but matches the placeholders backwards
     * from the end to the beginning of the input string.
     *
     *
     * This is also equivalent to allowing the left placeholder to match greedily, while still
     * requiring the remaining placeholder(s) to be matched.
     *
     * @return the return value of the `mapper` function if not null. Returns empty if `input` doesn't match the format, or `mapper` returns null.
     * @throws IllegalArgumentException if the format string doesn't have exactly 3 placeholders.
     * @since 7.0
     *//*

    */
/*fun <R> parseGreedy(
        input: String, mapper: Ternary<in String, out R>
    ): Optional<R> {
        return parseGreedyExpecting(3, input, combining(mapper))
    }*//*


    */
/**
     * Similar to [.parse], parses `input` and applies `mapper`
     * with the 3 placeholder values in this format string, but matches the placeholders backwards
     * from the end to the beginning of the input string.
     *
     *
     * This is also equivalent to allowing the left placeholder to match greedily, while still
     * requiring the remaining placeholder(s) to be matched.
     *
     * @return the return value of the `mapper` function if not null. Returns empty if `input` doesn't match the format, or `mapper` returns null.
     * @throws IllegalArgumentException if the format string doesn't have exactly 4 placeholders.
     * @since 7.0
     *//*

    */
/*fun <R> parseGreedy(
        input: String, mapper: Quarternary<in String, out R>
    ): Optional<R> {
        return parseGreedyExpecting(4, input, combining(mapper))
    }*//*


    */
/**
     * Similar to [.parse], parses `input` and applies `mapper`
     * with the 5 placeholder values in this format string, but matches the placeholders backwards
     * from the end to the beginning of the input string.
     *
     *
     * This is also equivalent to allowing the left placeholder to match greedily, while still
     * requiring the remaining placeholder(s) to be matched.
     *
     * @return the return value of the `mapper` function if not null. Returns empty if `input` doesn't match the format, or `mapper` returns null.
     * @throws IllegalArgumentException if the format string doesn't have exactly 5 placeholders.
     * @since 7.0
     *//*

   */
/* fun <R> parseGreedy(
        input: String, mapper: Quinary<in String, out R>
    ): Optional<R> {
        return parseGreedyExpecting(5, input, combining(mapper))
    }
*//*

    */
/**
     * Returns true if this format matches `input` entirely.
     *
     * @since 7.0
     *//*

    fun matches(input: String): Boolean {
        return parse(input).isPresent
    }

    */
/**
     * Scans the `input` string and extracts all matched placeholders in this string format.
     *
     *
     * unlike [.parse], the input string isn't matched entirely: the pattern doesn't
     * have to start from the beginning, and if there are some remaining characters that don't match
     * the pattern any more, the stream stops. In particular, if there is no match, empty stream is
     * returned.
     *//*

    fun scan(input: String): Stream<List<SubPatternMatch>> {
        if (format.isEmpty()) {
            return Stream.generate<List<Substring.SubPatternMatch>>(Supplier<List<Substring.SubPatternMatch>> { emptyList<Substring.SubPatternMatch>() })
                .limit((input.length + 1).toLong())
        }
        val numPlaceholders = numPlaceholders()
        return whileNotNull(
            object : Supplier<List<SubPatternMatch>?> {
                private var inputIndex = 0
                private var done = false
                override fun get(): List<SubPatternMatch>? {
                    if (done) {
                        return null
                    }
                    inputIndex = input.indexOf(fragments.get(0), inputIndex)
                    if (inputIndex < 0) {
                        return null
                    }
                    inputIndex += fragments.get(0).length
                    val builder: MutableList<SubPatternMatch> =
                        ArrayList<SubPatternMatch>(numCapturingPlaceholders)
                    for (i in 1..numPlaceholders) {
                        val literal = fragments.get(i)
                        // Always search left-to-right. The last placeholder at the end of format is suffix.
                        val literalLocator: SubPattern =
                            if (i == numPlaceholders && fragments.get(i)
                                    .isEmpty()
                            ) Substring.END else first(fragments.get(i))
                        val placeholder: SubPatternMatch = before(literalLocator).match(input, inputIndex) ?: return null
                        if (toCapture.get(i - 1)) {
                            builder.add(placeholder)
                        }
                        inputIndex = placeholder.index() + placeholder.length + literal.length
                    }
                    if (inputIndex == input.length) {
                        done = true
                    }
                    return Collections.unmodifiableList(builder)
                }
            })
    }

    */
/**
     * Scans the `input` string and extracts all matches of this string format. Returns the lazy
     * stream of non-null results from passing the single placeholder values to the `mapper`
     * function for each iteration, with null results skipped.
     *
     *
     * For example:
     *
     * <pre>`new StringFormat("/home/usr/myname/{file_name}\n")
     * .scan(multiLineInput, fileName -> ...);
    `</pre> *
     *
     *
     * unlike [.parse], the input string isn't matched entirely: the
     * pattern doesn't have to start from the beginning, and if there are some remaining characters
     * that don't match the pattern any more, the stream stops. In particular, if there is no match,
     * empty stream is returned.
     *
     *
     * By default, placeholders are allowed to be matched against an empty string. If the
     * placeholder isn't expected to be empty, consider filtering it out by returning null from the
     * `mapper` function, which will then be ignored in the result stream.
     *//*

    fun <R> scan(input: String, mapper: Function<in String, out R>): Stream<R> {
        checkPlaceholderCount(1)
        return scanAndCollect(input, onlyElement(mapper))
    }

    */
/**
     * Scans the `input` string and extracts all matches of this string format. Returns the lazy
     * stream of non-null results from passing the two placeholder values to the `mapper`
     * function for each iteration, with null results skipped.
     *
     *
     * For example:
     *
     * <pre>`new StringFormat("[key={key}, value={value}]")
     * .repeatedly()
     * .parse(input, (key, value) -> ...);
    `</pre> *
     *
     *
     * unlike [.parse], the input string isn't matched entirely: the
     * pattern doesn't have to start from the beginning, and if there are some remaining characters
     * that don't match the pattern any more, the stream stops. In particular, if there is no match,
     * empty stream is returned.
     *
     *
     * By default, placeholders are allowed to be matched against an empty string. If a certain
     * placeholder isn't expected to be empty, consider filtering it out by returning null from the
     * `mapper` function, which will then be ignored in the result stream.
     *//*

    fun <R> scan(
        input: String, mapper: BiFunction<in String, in String, out R>
    ): Stream<R> {
        checkPlaceholderCount(2)
        return scanAndCollect(input, combining(mapper))
    }

    */
/**
     * Scans the `input` string and extracts all matches of this string format. Returns the lazy
     * stream of non-null results from passing the 3 placeholder values to the `mapper` function
     * for each iteration, with null results skipped.
     *
     *
     * For example:
     *
     * <pre>`new StringFormat("[{lhs} + {rhs} = {result}]")
     * .repeatedly()
     * .parse(input, (lhs, rhs, result) -> ...);
    `</pre> *
     *
     *
     * unlike [.parse], the input string isn't matched entirely: the pattern
     * doesn't have to start from the beginning, and if there are some remaining characters that don't
     * match the pattern any more, the stream stops. In particular, if there is no match, empty stream
     * is returned.
     *
     *
     * By default, placeholders are allowed to be matched against an empty string. If a certain
     * placeholder isn't expected to be empty, consider filtering it out by returning null from the
     * `mapper` function, which will then be ignored in the result stream.
     *//*

   */
/* fun <R> scan(input: String, mapper: Ternary<in String, out R>): Stream<R> {
        checkPlaceholderCount(3)
        return scanAndCollect(input, combining(mapper))
    }*//*


    */
/**
     * Scans the `input` string and extracts all matches of this string format. Returns the lazy
     * stream of non-null results from passing the 4 placeholder values to the `mapper` function
     * for each iteration, with null results skipped.
     *
     *
     * unlike [.parse], the input string isn't matched entirely: the
     * pattern doesn't have to start from the beginning, and if there are some remaining characters
     * that don't match the pattern any more, the stream stops. In particular, if there is no match,
     * empty stream is returned.
     *
     *
     * By default, placeholders are allowed to be matched against an empty string. If a certain
     * placeholder isn't expected to be empty, consider filtering it out by returning null from the
     * `mapper` function, which will then be ignored in the result stream.
     *//*

    */
/*fun <R> scan(input: String, mapper: Quarternary<in String, out R>): Stream<R> {
        checkPlaceholderCount(4)
        return scanAndCollect(input, combining(mapper))
    }*//*


    */
/**
     * Scans the `input` string and extracts all matches of this string format. Returns the lazy
     * stream of non-null results from passing the 5 placeholder values to the `mapper` function
     * for each iteration, with null results skipped.
     *
     *
     * unlike [.parse], the input string isn't matched entirely: the pattern
     * doesn't have to start from the beginning, and if there are some remaining characters that don't
     * match the pattern any more, the stream stops. In particular, if there is no match, empty stream
     * is returned.
     *
     *
     * By default, placeholders are allowed to be matched against an empty string. If a certain
     * placeholder isn't expected to be empty, consider filtering it out by returning null from the
     * `mapper` function, which will then be ignored in the result stream.
     *//*

    */
/*fun <R> scan(input: String, mapper: Quinary<in String, out R>): Stream<R> {

        checkPlaceholderCount(5)
        return scanAndCollect(input, combining(mapper))
    }*//*


    */
/**
     * Scans the `input` string and extracts all matches of this string format. Returns the lazy
     * stream of non-null results from passing the 6 placeholder values to the `mapper` function
     * for each iteration, with null results skipped.
     *
     *
     * unlike [.parse], the input string isn't matched entirely: the pattern
     * doesn't have to start from the beginning, and if there are some remaining characters that don't
     * match the pattern any more, the stream stops. In particular, if there is no match, empty stream
     * is returned.
     *
     *
     * By default, placeholders are allowed to be matched against an empty string. If a certain
     * placeholder isn't expected to be empty, consider filtering it out by returning null from the
     * `mapper` function, which will then be ignored in the result stream.
     *//*

    */
/*fun <R> scan(input: String, mapper: Senary<in String, out R>): Stream<R> {
        checkPlaceholderCount(6)
        return scanAndCollect(input, combining(mapper))
    }*//*


    */
/**
     * Returns the string formatted with placeholders filled using `args`. This is the reverse
     * operation of the `parse(...)` methods. For example:
     *
     * <pre>`new StringFormat("Hello {who}").format("world")
     * => "Hello world"
    `</pre> *
     *
     * @throws IllegalArgumentException if the number of arguments doesn't match that of the
     * placeholders
     *//*

    fun format(vararg args: Any): String {
        checkFormatArgs(args)
        val builder = StringBuilder().append(fragments.get(0))
        for (i in args.indices) {
            builder.append(args.get(i)).append(fragments.get(i + 1))
        }
        return builder.toString()
    }

    */
/** Returns the string format.  *//*

    override fun toString(): String {
        return format
    }

    private fun <R> parseGreedyExpecting(
        cardinality: Int, input: String, collector: Collector<in String, *, R>
    ): Optional<R> {
        checkPlaceholderCount(cardinality)
        // To match backwards, we reverse the input as well as the format string.
        // After the matching is done, reverse the results back.
        return internalParse(
            reverse(input),
            reverse<String>(fragments).stream().map<String> { s: String ->
                reverse(
                    s
                )
            }.collect(toList()),
            reverse(toCapture)
        )
            .map(
                Function<List<Substring.SubPatternMatch>, R> { captured: List<Substring.SubPatternMatch> ->
                    reverse(captured).stream()
                        .map { sub ->  // Return the original (unreversed) substring
                            val forwardIndex: Int = input.length - (sub.index() + sub.length)
                            input.substring(forwardIndex, forwardIndex + sub.length)
                        }
                        .collect(collector)
                })
    }

    private fun <R> parseExpecting(
        cardinality: Int, input: String, collector: Collector<in String, *, R>
    ): Optional<R> {
        checkPlaceholderCount(cardinality)
        return parse(input).map(Function { values: List<SubPatternMatch> ->
            values.stream().map(SubPatternMatch::toString).collect(collector)
        })
    }

    */
/**
     * Parses `input` with the number of placeholders equal to `cardinality`, then
     * collects the placeholder values using `collector`.
     *
     * @throws IllegalArgumentException if input fails parsing
     *//*

    private fun <R> parseOrThrowExpecting(
        cardinality: Int, input: String, collector: Collector<in String, *, R>
    ): R {
        checkPlaceholderCount(cardinality)
        val values: List<SubPatternMatch> = parse(input)
            .orElseThrow(
                Supplier<IllegalArgumentException> {
                    IllegalArgumentException(
                        StringFormat("input '{input}' doesn't match format string '{format}'")
                            .format(input, format)
                    )
                })
        val result: R = values.stream().map(Substring.SubPatternMatch::toString).collect(collector)
            ?: throw NullPointerException(
                String.format(
                    "mapper function returned null when matching input '%s' against format string '%s'",
                    input, format
                )
            )
        return result
    }

    private fun <R> scanAndCollect(
        input: String,
        collector: Collector<in String, *, R>
    ): Stream<R> {
        return scan(input)
            .map(Function{ values: List<SubPatternMatch> ->
                values.stream().map(Substring.SubPatternMatch::toString).collect(collector)
            })
            .filter { v: Any? -> v != null }
    }

    private fun numPlaceholders(): Int {
        return fragments.size - 1
    }

    private fun checkUnformattability() {
        for (i in 1 until numPlaceholders()) {
            if (fragments[i].isEmpty()) {
                throw IllegalArgumentException("Placeholders cannot be next to each other: $format")
            }
        }
    }

    private fun checkPlaceholderCount(expected: Int) {
        if (numCapturingPlaceholders != expected) {
            throw IllegalArgumentException(
                String.format(
                    "format string has %s placeholders; %s expected.",
                    numCapturingPlaceholders,
                    expected
                )
            )
        }
    }

    fun checkFormatArgs(args: Array<out Any>) {
        if (args.size != numPlaceholders()) {
            throw IllegalArgumentException(
                String.format(
                    "format string expects %s placeholders, %s provided",
                    numPlaceholders(),
                    args.size
                )
            )
        }
    }

    companion object {
        fun reverse(s: String): String {
            if (s.length <= 1) {
                return s
            }
            val builder = StringBuilder(s.length)
            for (i in s.length - 1 downTo 0) {
                builder.append(s[i])
            }
            return builder.toString()
        }

        fun <T> reverse(list: List<T>): List<T> {
            if (list.size <= 1) {
                return list
            }
            return object : AbstractList<T>() {
                
                override fun get(i: Int): T {
                    return list[list.size - 1 - i]
                }

                override val size: Int get() = list.size
            }
        }

        private fun <T> chop(list: List<T>): List<T> {
            return list.subList(0, list.size - 1)
        }
    }
}

*/
/**
 * A string parser to extract placeholder values from input strings according to a format string.
 * For example:
 *
 * <pre>`return new StringFormat("{address}+{subaddress}@{domain}")
 * .parse("my-ldap+test@google.com", (address, subaddress, domain) -> ...);
`</pre> *
 *
 *
 * An ErrorProne check is provided to guard against incorrect lambda parameters to the `parse()`, `parseOrThrow()`, `parseGreedy()` and `scan()` methods. Both the
 * number of parameters and the lambda parameter names are checked to ensure they match the format
 * string. The arguments passed to the [.format] are also checked. If you use bazel, the check
 * is automatically enforced.
 *
 *
 * Starting from 6.7, if a certain placeholder is uninteresting and you'd rather not name it, you
 * can use the special `...` placeholder and then you won't need to assign a lambda variable
 * to capture it:
 *
 * <pre>`return new StringFormat("{...}+{subaddress}@{domain}")
 * .parse("my-ldap+test@google.com", (subaddress, domain) -> ...);
`</pre> *
 *
 *
 * Note that except the placeholders, characters in the format string are treated as literals.
 * This works better if your pattern is close to free-form text with characters like '.', '?', '(',
 * '|' and whatnot because you don't need to escape them. On the other hand, the literal characters
 * won't offer regex functionalities you get from `(\w+)`, `(foo|bar)` etc.
 *
 *
 * In the face of ambiguity, the `parse()` methods can be lossy. Consider the format string
 * of `String.format("I bought %s and %s", "apples and oranges", "chips")`, it returns `"I bought apples and oranges and chips"`; but the following parsing code will incorrectly parse
 * "apples" as "{fruits}" and "oranges and chips" as "{snacks}":
 *
 * <pre>`new StringFormat("I bought {fruits} and {snacks}")
 * .parse("I bought apples and oranges and chips", (fruits, snacks) -> ...);
`</pre> *
 *
 * As such, only use this class on trusted input strings (i.e. not user inputs). And use regex
 * instead to better deal with ambiguity.
 *
 *
 * All the `parse()` methods attempt to match the entire input string from beginning to
 * end. If you need to find the string format as a substring anywhere inside the input string, or
 * need to find repeated occurrences from the input string, use the `scan()` methods instead.
 * Tack on `.findFirst()` on the returned lazy stream if you only care to find a single
 * occurrence.
 *
 *
 * This class is immutable and pre-compiles the format string at constructor time so that the
 * `parse()` and `scan()` methods will be more efficient.
 *
 * @since 6.6
 *//*

class StringFormat(format: String) : AbstractStringFormat(format, PLACEHOLDERS, "{...}") {
    */
/**
     * A view of the `StringFormat` that returns an instance of `T`, after filling the
     * format with the given variadic parameters.
     *
     * @since 7.0
     *//*

    interface To<T> {
        */
/** Returns an instance of `T` from the string format filled with `params`.  *//*

        fun with(vararg params: Any): T

        */
/** Returns the string representation of the format.  *//*

        abstract override fun toString(): String
    }

    */
/**
     * A functional SPI interface for custom interpolation.
     *
     * @since 7.0
     *//*

  fun interface Interpolator<T> {
        */
/**
         * Interpolates with `fragments` of size `N + 1` and `placeholders` of size
         * `N`. The `placeholders` BiStream includes pairs of placeholder names in the form
         * of "{foo}" and their corresponding values passed through the varargs parameter of [ ][To.with].
         *//*

        fun interpolate(
            fragments: List<String>,
            placeholders: List<SubPatternMatch>,
            vararg params: Any
        ): T
    }

    companion object {
        private val PLACEHOLDERS =
            consecutive(CharPredicate { ch -> ch != '{' && ch != '}' }) // Find the inner-most pairs of curly braces.
                .immediatelyBetween("{", Substring.BoundStyle.INCLUSIVE, "}",
                    Substring.BoundStyle.INCLUSIVE
                )
                .repeatedly()

        */
/**
         * Returns a [Substring.SubPattern] spanning the substring matching `format`. For
         * example, `StringFormat.span("projects/{project}/")` is equivalent to `spanningInOrder("projects/", "/")`.
         *
         *
         * Useful if you need a Substring.SubPattern for purposes such as composition, but prefer a more
         * self-documenting syntax. The placeholder names in the format string don't affect runtime
         * semantics, but using meaningful names improves readability.
         *
         * @since 7.0
         *//*

        fun span(format: String): SubPattern {
            val delimiters = PLACEHOLDERS.split(format).map(Substring.SubPatternMatch::toString).collect(toList())
            // If the last placeholder is at end, treat it as anchoring to the end.
            return if (delimiters.size > 1 && delimiters[delimiters.size - 1].isEmpty())
                spanInOrder(delimiters.subList(0, delimiters.size - 1)).toEnd()
            else
                spanInOrder(delimiters)
        }

        private fun spanInOrder(goalPosts: List<String>):SubPattern {
            return goalPosts.stream()
                .skip(1)
                .map(Substring::first)
                .reduce(first(goalPosts[0]),SubPattern::extendTo)
        }

        */
/**
         * Returns a factory of type `T` using `format` string as the template, whose
         * curly-braced placeholders will be filled with the template arguments and then passed to the
         * `creator` function to create the `T` instances.
         *
         *
         * A typical use case is to pre-create an exception template that can be used to create
         * exceptions filled with different parameter values. For example:
         *
         * <pre>`private static final StringFormat.To<IOException> JOB_FAILED =
         * StringFormat.to(
         * IOException::new, "Job ({job_id}) failed with {error_code}, details: {details}");
         *
         * // 150 lines later.
         * // Compile-time enforced that parameters are correct and in the right order.
         * throw JOB_FAILED.with(jobId, errorCode, errorDetails);
        `</pre> *
         *
         * @since 7.0
         *//*

        fun <T> to(
            creator: Function<in String, out T>, format: String
        ): To<T> {
            val fmt = StringFormat(format)
            return object : To<T> {
                override fun with(vararg params: Any): T {
                    return creator.apply(fmt.format(*params))
                }
                override fun toString(): String {
                    return format
                }
            }
        }

        */
/**
         * Returns a go/jep-430 style template of `T` produced by interpolating arguments into the
         * `template` string, using the given `interpolator` function.
         *
         *
         * The `interpolator` function is an SPI. That is, instead of users creating the lambda
         * in-line, you are expected to provide a canned implementation -- typically by wrapping it inside
         * a convenient facade class. For example:
         *
         * <pre>`// Provided to the user:
         * public final class BigQuery {
         * public static StringFormat.To<QueryRequest> template(String template) {
         * return StringFormat.template(template, (fragments, placeholders) -> ...);
         * }
         * }
         *
         * // At call site:
         * private static final StringFormat.To<QueryRequest> GET_CASE_BY_ID = BigQuery.template(
         * "SELECT CaseId, Description FROM tbl WHERE CaseId = '{case_id}'");
         *
         * ....
         * QueryRequest query = GET_CASE_BY_ID.with(caseId);  // automatically escape special chars
        `</pre> *
         *
         *
         * This way, the StringFormat API provides compile-time safety, and the SPI plugs in custom
         * interpolation logic.
         *
         *
         * Calling [To.with] with unexpected number of parameters will throw [ ] without invoking `interpolator`.
         *
         * @since 7.0
         *//*

        fun <T> template(template: String, interpolator: Interpolator<out T>): To<T> {
            val formatter = StringFormat(template)
            val placeholders: List<SubPatternMatch> = PLACEHOLDERS.match(template).collect(toList())
            return object : To<T> {
                override fun with(vararg params: Any): T {
                    formatter.checkFormatArgs(params)
                    return interpolator.interpolate(
                        formatter.fragments,
                        placeholders,
                        params
                    )
                }

                override fun toString(): String {
                    return template
                }
            }
        }
    }
}

*/
/**
 * Returns a collector that collects the only two elements from the input and transforms them
 * using the `mapper` function. If there are fewer or more elements in the input,
 * IllegalArgumentExceptioin is thrown.
 *
 *
 * To handle the `size() != 2` case, consider to use the [ ][MoreCollections.findOnlyElements] method,
 * which returns [Optional].
 *
 * @since 6.6
 *//*

fun <T, R> combining(
    mapper: BiFunction<in T, in T, out R>
): FixedSizeCollector<T, *, R> {
    return object : ShortListCollector<T, R>() {
        override fun reduce(list: List<T>): R {
            return mapper.apply(list[0], list[1])
        }

        override fun arity(): Int {
            return 2
        }
    }
}

*/
/**
 * Same as [.asIn].
 *
 * @since 5.4
 *//*

fun <T, R> onlyElement(
    mapper: Function<in T, out R>
): FixedSizeCollector<T, *, R> {
    return object : ShortListCollector<T, R>() {
        override fun reduce(list: List<T>): R {
            return mapper.apply(list[0])
        }

        override fun arity(): Int {
            return 1
        }
    }
}

*/
/**
 * A collector that expects a fixed number of input elements.
 *
 *
 * In addition to being used as regular Collector, can also be passed as one of the
 * multiple conditional cases to [MoreCollectors.switching].
 *
 * @since 5.5
 *//*

abstract class FixedSizeCollector<T, A, R> : Collector<T, A, R> {
    fun appliesTo(list: List<T>): Boolean {
        return list.size == arity()
    }

    abstract fun arity(): Int
    abstract fun reduce(list: List<T>): R
}

*/
/**
 * Utility class to perform n-ary functional pattern matching on a list or a stream of input elements.
 *
 * @since 5.3
 *//*

internal abstract class ShortListCollector<T, R> : FixedSizeCollector<T, MutableList<T>, R>() {
    override fun accumulator(): BiConsumer<MutableList<T>, T> {
        return BiConsumer<MutableList<T>, T> { obj: MutableList<T>, e: T ->
            obj.add(e)
        }
    }

    override fun combiner(): BinaryOperator<MutableList<T>> {
        return BinaryOperator<MutableList<T>> { l1: MutableList<T>, l2: List<T> ->
            l1.addAll(l2)
            l1
        }
    }

    override fun finisher(): Function<MutableList<T>, R> {
        return Function { list: MutableList<T> ->
            collectOrThrow(list)
        }
    }

    override fun characteristics(): Set<Collector.Characteristics> {
        return emptySet()
    }

    override fun supplier(): Supplier<MutableList<T>> {
        return Supplier<MutableList<T>> {
            ArrayList(arity())
        }
    }

    override fun toString(): String {
        return arity().toString() + " elements"
    }

    */
/**
     * Use this collector to collect elements from `list` if it's of the expected size,
     * or else throws [IllegalArgumentException].
     *//*

    private fun collectOrThrow(list: List<T>): R {
        if (appliesTo(list)) return reduce(list)
        throw java.lang.IllegalArgumentException(
            "Not true that input " + showShortList(list, arity() + 1) + " has " + this + "."
        )
    }

    companion object {
        fun showShortList(list: List<*>, elementsToShow: Int): String {
            // If small enough, just show it.
            return if (list.size <= elementsToShow)
                       "<$list>"
                   else
                       ("of size = " + list.size + " <[" + list.stream().limit(elementsToShow.toLong())
                              .map { obj: Any? -> obj.toString() }
                              .collect(Collectors.joining(", "))
                              + ", ...]>")
        }
    }
}*/
